`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date: 2020/05/13 23:55:28
// Design Name: 
// Module Name: insert_cpu_w_ctrl
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 插入CPU接口,CPU每次写32位,RAM是128位,所以要写4次RAM写地址才加1
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////
// //
// $Log$
//	2021.6.7 RAM读出的数据用寄存器打一拍-lhb
// *********************************************************************
`include "top_define.v"
module insert_cpu_w_ctrl(
	input clk    	   ,
	input rst_n        ,
    input [9:0]ram_2p_cfg_register,
	
	input insert_end , //用于最后未满128bit数据的写入//CPU将数据插入到RAM完成后给出插入结束信号
	
(*mark_debug = "true"*)	input  dpram0_wren          ,
//(*mark_debug = "true"*)	input  [8:0]  dpram0_waddr  ,
(*mark_debug = "true"*)	input  [31:0] dpram0_wdata  ,
//(*mark_debug = "true"*)	input  dpram0_rden          ,
(*mark_debug = "true"*)	input  [5:0]   dpram0_raddr ,
(*mark_debug = "true"*)	output reg [255:0] dpram0_rdata
    );

//REGS
reg [2:0] write_cnt ; //写计数,写四次就地址加一
//reg write_state     ; //写数据状态

reg insert_end_dl1 ;
reg insert_end_dl2 ;
reg insert_end_dl3 ;

//dpram0
//reg dpram0_wren_dl           ;
reg dpram0_wren_act          ; //后缀act表示直接连接ram的信号
reg [5:0]  dpram0_waddr_act  ;
reg [255:0] dpram0_wdata_act ;

//WIRE
//wire dpram0_wren_pos ;
//wire dpram0_wren_neg ;
wire insert_end_pos_dl1 ;
wire insert_end_pos_dl2 ;

wire [5:0]   dpram0_raddr_act;
wire [255:0] dpram0_rdata_act;
//MAIN CODE
//assign dpram0_wren_pos = ( dpram0_wren == 1'b1 ) && ( dpram0_wren_dl == 1'b0 ) ;
//assign dpram0_wren_neg = ( dpram0_wren == 1'brx_axis_tvalid_10 ) && ( dpram0_wren_dl == 1'b1 ) ;
assign insert_end_pos_dl1 = ( insert_end_dl1 == 1'b1 ) && ( insert_end_dl2 == 1'b0 ) ;
assign insert_end_pos_dl2 = ( insert_end_dl2 == 1'b1 ) && ( insert_end_dl3 == 1'b0 ) ;

//insert_end信号打拍
always @( posedge clk or negedge rst_n )
begin
	if ( rst_n == 1'b0 ) begin
		insert_end_dl1 <= 1'b0 ; 
	    insert_end_dl2 <= 1'b0 ;
		insert_end_dl3 <= 1'b0 ;
	end
	else begin
		insert_end_dl1 <= insert_end     ; 
	    insert_end_dl2 <= insert_end_dl1 ;
		insert_end_dl3 <= insert_end_dl2 ;
	end 
end 

//写计数,累计4次,或者最后未满128bit写进ram
always @( posedge clk or negedge rst_n )
begin
	if ( rst_n == 1'b0 )
		write_cnt <= 3'd0 ; 
	else if ( insert_end_pos_dl1 == 1'b1 )
		write_cnt <= 3'd0 ; 
	else if ( dpram0_wren == 1'b1 ) 
		if ( write_cnt == 3'd7 )
			write_cnt <= 3'd0 ; 
		else
			write_cnt <= write_cnt + 3'd1 ;  
	else 
		write_cnt <= write_cnt ; 
end 

////写数据状态
//always @( posedge clk or negedge rst_n )
//begin
//	if ( rst_n == 1'b0 )
//		write_state <= 1'b0 ; 
//	else if ( dpram0_wren == 1'b1 ) 
//		write_state <= 1'b1 ;   
//	else if ( insert_end == 1'b1 )
//		write_state <= 1'b0 ;
//	else 
//		write_state <= write_state ; 
//end 


//***********************dpram0**************************
////写使能打拍
//always @( posedge clk or negedge rst_n )
//begin
//	if ( rst_n == 1'b0 )
//		dpram0_wren_dl <= 1'b0 ; 
//	else 
//		dpram0_wren_dl <= dpram0_wren ; 
//end 

//直接连接ram的写使能信号
always @( posedge clk or negedge rst_n )
begin
	if ( rst_n == 1'b0 )
		dpram0_wren_act <= 1'b0 ; 
	else if ( ( write_cnt == 3'd7 && dpram0_wren == 1'b1 ) || ( insert_end_pos_dl1 == 1'b1 && write_cnt != 3'd0 ) )
		dpram0_wren_act <= 1'b1 ; 
	else
		dpram0_wren_act <= 1'b0 ; 
end

//直接连接ram的写数据
always @( posedge clk or negedge rst_n )
begin
	if ( rst_n == 1'b0 )
		dpram0_wdata_act <= 256'b0 ; 
	else if ( insert_end_pos_dl1 == 1'b1 && write_cnt != 3'd0 )
		case(write_cnt)
			3'd1 : dpram0_wdata_act <= { dpram0_wdata_act[255:224] , 224'b0 } ; 
			3'd2 : dpram0_wdata_act <= { dpram0_wdata_act[255:192] , 192'b0 } ; 
			3'd3 : dpram0_wdata_act <= { dpram0_wdata_act[255:160] , 160'b0 } ;
			3'd4 : dpram0_wdata_act <= { dpram0_wdata_act[255:128] , 128'b0 } ; 
			3'd5 : dpram0_wdata_act <= { dpram0_wdata_act[255:96] , 96'b0 } ; 
			3'd6 : dpram0_wdata_act <= { dpram0_wdata_act[255:64] , 64'b0 } ;
			3'd7 : dpram0_wdata_act <= { dpram0_wdata_act[255:32] , 32'b0 } ;
		    default:dpram0_wdata_act <= dpram0_wdata_act ;
		endcase
	else if ( dpram0_wren == 1'b1 ) 
		case(write_cnt)
			3'd0 : dpram0_wdata_act <= { dpram0_wdata , dpram0_wdata_act[223:0] } ; 
		    3'd1 : dpram0_wdata_act <= { dpram0_wdata_act[255:224] , dpram0_wdata , dpram0_wdata_act[191:0] } ; 
		    3'd2 : dpram0_wdata_act <= { dpram0_wdata_act[255:192] , dpram0_wdata , dpram0_wdata_act[159:0] } ; 
		    3'd3 : dpram0_wdata_act <= { dpram0_wdata_act[255:160] , dpram0_wdata , dpram0_wdata_act[127:0] } ; 
			3'd4 : dpram0_wdata_act <= { dpram0_wdata_act[255:128] , dpram0_wdata , dpram0_wdata_act[95:0] } ; 
		    3'd5 : dpram0_wdata_act <= { dpram0_wdata_act[255:96] , dpram0_wdata , dpram0_wdata_act[63:0] } ; 
		    3'd6 : dpram0_wdata_act <= { dpram0_wdata_act[255:64] , dpram0_wdata , dpram0_wdata_act[31:0] } ; 
		    3'd7 : dpram0_wdata_act <= { dpram0_wdata_act[255:32] , dpram0_wdata } ;  
		    default:dpram0_wdata_act <= dpram0_wdata_act ;
		endcase
	else
		dpram0_wdata_act <= dpram0_wdata_act ;
end 

//直接连接ram的写地址
always @( posedge clk or negedge rst_n )
begin
	if ( rst_n == 1'b0 )
		dpram0_waddr_act <= 6'd63 ; 
	else if ( insert_end_pos_dl2 == 1'b1 ) 
		dpram0_waddr_act <= 6'd63 ; 
	else if ( ( write_cnt == 3'd7 && dpram0_wren == 1'b1 ) || ( insert_end_pos_dl1 == 1'b1 && write_cnt != 3'd0 ) )
		dpram0_waddr_act <= dpram0_waddr_act + 6'b1 ;  
	else
		dpram0_waddr_act <= dpram0_waddr_act ; 
end 


//***********************dpram**************************
`ifdef ASIC
ram_2p_d64_w256_wrapper U_dpram0_asic(
.clk(clk),
.ram_2p_cfg_register(ram_2p_cfg_register),
.wren(dpram0_wren_act),
.waddr(dpram0_waddr_act),
.wdata(dpram0_wdata_act),
.rden(1'b1/*dpram0_rden*/),
.raddr(dpram0_raddr_act),
.rdata(dpram0_rdata_act)
);
`endif
`ifdef FPGA
dpram0 U_dpram0 (
  .clka(clk),              // input wire clka
  .wea(dpram0_wren_act),       // input wire [0 : 0] wea
  .addra(dpram0_waddr_act),    // input wire [6 : 0] addra
  .dina(dpram0_wdata_act),     // input wire [127 : 0] dina
  .clkb(clk),            // input wire clkb
  .enb (1'b1),
  .addrb(dpram0_raddr_act),        // input wire [6 : 0] addrb
  .doutb(dpram0_rdata_act )        // output wire [127 : 0] doutb
);
`endif

assign dpram0_raddr_act = dpram0_raddr;

always @(posedge clk or negedge rst_n) begin
	if (rst_n == 1'b0) begin
		dpram0_rdata <= 256'b0;
	end
	else begin
		dpram0_rdata <= dpram0_rdata_act;
	end
end

endmodule
